package com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.repository;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.FlowBaseDataHandleProcessor;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.BeanCopierUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.form.FormProcessInstanceHandleRelDto;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.form.FormProcessInstanceHandleRelVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.form.HttpProcessInstanceHandleRelVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowProcessInstanceHandleRelRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowTitleExpressionResultRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.entities.FlowFormProcessInstanceHandleRel;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.entities.FormProcessInstanceHandleRelExample;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.mapper.FormProcessInstanceHandleRelDAO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
　　* @description: 数据持久化层实现
　　* @author shenrm
　　* @date 2021/10/19 17:17
　　*/
@Slf4j
@Repository
public class FlowProcessInstanceHandleRelRepositoryImpl implements FlowProcessInstanceHandleRelRepository {


    @Autowired
    private FormProcessInstanceHandleRelDAO formProcessInstanceHandleRelDAO;

    @Autowired
    private FlowBaseDataHandleProcessor flowBaseDataHandleProcessor;

    @Autowired
    private FlowTitleExpressionResultRepository flowTitleExpressionResultRepository;

    /**
     * 批量插入数据
     * @param handleRelDtoList
     * @return
     */
    @Override
    public int batchInsertFlowFormProcessInstanceHandleRel(List<FormProcessInstanceHandleRelDto> handleRelDtoList) {
        if(CollectionUtils.isNotEmpty(handleRelDtoList)) {
            List<FlowFormProcessInstanceHandleRel> flowProcessInstanceHandleRelList = new ArrayList<FlowFormProcessInstanceHandleRel>(handleRelDtoList.size());
            for (FormProcessInstanceHandleRelDto relDto : handleRelDtoList){
                FlowFormProcessInstanceHandleRel handleRel = new FlowFormProcessInstanceHandleRel();
                BeanCopierUtils.copyProperties(relDto,handleRel);
                flowProcessInstanceHandleRelList.add(handleRel);
            }
            // 批量新增
            return formProcessInstanceHandleRelDAO.batchInsert(flowProcessInstanceHandleRelList);
        }
        return 0;
    }

    /**
     * 根据条件查询
     *
     * @param handleRelVo
     * @return
     */
    @Override
    public List<FormProcessInstanceHandleRelVo> selectByCondition(HttpProcessInstanceHandleRelVo handleRelVo) {
        PageHelper.startPage(handleRelVo.getPageNum(), handleRelVo.getPageSize());
        FormProcessInstanceHandleRelExample queryCondition = new FormProcessInstanceHandleRelExample();
        // 添加条件
        FormProcessInstanceHandleRelExample.Criteria criteria = queryCondition.createCriteria();

        // 添加阅办人查询条件
        criteria.andHandlerIdEqualTo(handleRelVo.getReadCopyTo());

        // 处理类型不为空时,则添加处理类型作为查询条件查询
        if(StringUtils.isNotBlank(handleRelVo.getHandleType())) {
            criteria.andHandlerTypeEqualTo(handleRelVo.getHandleType());
        }

        // 处理状态不为空时,则添加处理状态作为查询条件查询
        if(Objects.nonNull(handleRelVo.getStatus())) {
            criteria.andStatusEqualTo(handleRelVo.getStatus());
        }

        // 来源应用编码
        if(StringUtils.isNotBlank(handleRelVo.getSourceAppCode())) {
            criteria.andSourceAppCodeEqualTo(handleRelVo.getSourceAppCode());
        }

        // 业务编码(大分类)
        if(StringUtils.isNotBlank(handleRelVo.getBusinessCode())) {
            criteria.andBusinessCodeEqualTo(handleRelVo.getBusinessCode());
        }

        // 业务模块编码
        if(StringUtils.isNotBlank(handleRelVo.getBusinessModuleCode())) {
            criteria.andBusinessModuleCodeEqualTo(handleRelVo.getBusinessModuleCode());
        }

        // 表单模块编码
        if(StringUtils.isNotBlank(handleRelVo.getFormModuleCode())) {
            criteria.andFormModuleCodeEqualTo(handleRelVo.getFormModuleCode());
        }

        // 排序字段
        String orderByClause = handleRelVo.getOrderByClause();

        // 设置排序字段, 默认按照创建时间降序
        if(StringUtils.isNotEmpty(orderByClause) && StringUtils.isNotEmpty(orderByClause.trim())){
            queryCondition.setOrderByClause(orderByClause);
        }else{
            queryCondition.setOrderByClause("create_time desc");
        }
        return getPageableResult(getHandleRels(queryCondition));
    }

    @Override
    public void updateByExampleSelective(String readCopyTo, List<String> taskIds,
                                        List<String> processInstanceIds, int readStatus) {
        FlowFormProcessInstanceHandleRel handleRel = new FlowFormProcessInstanceHandleRel();
        // 将其默认修改成已阅办状态
        handleRel.setStatus(readStatus);
        // 创建更新条件
        FormProcessInstanceHandleRelExample updateCondition = new FormProcessInstanceHandleRelExample();
        FormProcessInstanceHandleRelExample.Criteria criteria = updateCondition.createCriteria();

        // 添加更新条件
        // 添加处理人ID
        if(StringUtils.isNotBlank(readCopyTo)) {
            criteria.andHandlerIdEqualTo(readCopyTo);
        }

        // 添加流程实例ID
        if(CollectionUtils.isNotEmpty(processInstanceIds)) {
            criteria.andProcessInstanceIdIn(processInstanceIds);
        }

        // 添加流程实例中的节点ID集合
        if(CollectionUtils.isNotEmpty(taskIds)) {
            criteria.andTaskIdIn(taskIds);
        }
        formProcessInstanceHandleRelDAO.updateByExampleSelective(handleRel, updateCondition);
    }

    @Override
    public boolean isExistCheckData(List<String> readCopyTos, List<String> processInstanceIds, List<String> taskIds) {

        // 创建查询条件对象
        FormProcessInstanceHandleRelExample queryCondition = new FormProcessInstanceHandleRelExample();

        // 添加条件
        FormProcessInstanceHandleRelExample.Criteria criteria = queryCondition.createCriteria();

        // 添加阅办人查询条件
        criteria.andHandlerIdIn(readCopyTos);

        // 流程实例ID集合不为空时,则添加流程实例ID集合作为查询条件查询
        if(CollectionUtils.isNotEmpty(processInstanceIds)) {
            criteria.andProcessInstanceIdIn(processInstanceIds);
        }

        // 任务实例集合不为空时,则添加任务实例集合作为查询条件查询
        if(CollectionUtils.isNotEmpty(taskIds)) {
            criteria.andTaskIdIn(taskIds);
        }
        int count = formProcessInstanceHandleRelDAO.countByExample(queryCondition);
        if(count > 0) {
            return true;
        }
        return false;
    }

    @Override
    public List<FormProcessInstanceHandleRelVo> selectByConditionNoPage(String processInstanceId, String taskId) {
        // 创建查询条件对象
        FormProcessInstanceHandleRelExample queryCondition = new FormProcessInstanceHandleRelExample();

        // 添加条件
        FormProcessInstanceHandleRelExample.Criteria criteria = queryCondition.createCriteria();

        // 流程实例ID集合不为空时,则添加流程实例ID作为查询条件查询
        if(StringUtils.isNotBlank(processInstanceId)) {
            criteria.andProcessInstanceIdEqualTo(processInstanceId);
        }

        // 任务实例集合不为空时,则添加任务实例集合作为查询条件查询
        if(StringUtils.isNotBlank(taskId)) {
            criteria.andTaskIdEqualTo(taskId);
        }

        if (Objects.isNull(queryCondition)) {
            return null;
        }

        List<FlowFormProcessInstanceHandleRel> rtList = formProcessInstanceHandleRelDAO.selectByExample(queryCondition);
        return this.convertToVoNoPage(rtList);
    }

    private List<FormProcessInstanceHandleRelVo> getPageableResult(List<FlowFormProcessInstanceHandleRel> handleRelList) {
        PageInfo<FlowFormProcessInstanceHandleRel> pageInfo = new PageInfo<>(handleRelList);
        Page<FormProcessInstanceHandleRelVo> result = null;
        try {
            result = new Page<>();
            result.setPageNum(pageInfo.getPageNum()).setPageSize(pageInfo.getPageSize()).addAll(convert(handleRelList));
            result.setTotal(pageInfo.getTotal());
            return result;
        } finally {
            if (Objects.nonNull(result)) {
                result.close();
            }
        }
    }

    private List<FormProcessInstanceHandleRelVo> convert(List<FlowFormProcessInstanceHandleRel> sources) {
        if(CollectionUtils.isEmpty(sources)) {
            return Collections.emptyList();
        }

        // 循环翻译标题
        List<FormProcessInstanceHandleRelVo> handleRelVos = sources.stream().map(item -> {
            FormProcessInstanceHandleRelVo tmpVo = new FormProcessInstanceHandleRelVo();
            BeanUtils.copyProperties(item, tmpVo);
            // 流程实例ID
            String processInstanceId = "";
            // 流程定义名称
            String processDefinitionName = "";
            // 获取流程实例对象
            ProcessInstance processInstance = flowBaseDataHandleProcessor.resolveProcessInstance(item.getProcessInstanceId());
            if(Objects.isNull(processInstance)) {
                // 再查询下历史任务记录
                HistoricProcessInstance historicProcessInstance = flowBaseDataHandleProcessor.resolveHistoryProcessInstance(item.getProcessInstanceId());
                if (Objects.nonNull(historicProcessInstance)) {
                    processInstanceId = historicProcessInstance.getId();
                    processDefinitionName = historicProcessInstance.getProcessDefinitionName();
                }
            }else {
                processInstanceId = processInstance.getId();
                processDefinitionName = processInstance.getProcessDefinitionName();
            }

            // 任务节点编码
            String activityId = "";
            // 任务名称
            String taskName = "";
            // 任务实例
            Task task = flowBaseDataHandleProcessor.resolveTaskByProcessInstanceIdAndTaskId(item.getProcessInstanceId(), item.getTaskId());
            if(Objects.isNull(task)) {
                HistoricTaskInstance historyTask = flowBaseDataHandleProcessor.resolveHistoryTaskByTaskId(item.getTaskId());
                if(Objects.nonNull(historyTask)) {
                    activityId = historyTask.getTaskDefinitionKey();
                    taskName = historyTask.getName();
                }
            } else {
                activityId = task.getTaskDefinitionKey();
                taskName = task.getName();
            }

            if (StringUtils.isNotBlank(processInstanceId) &&
                    StringUtils.isNotBlank(processDefinitionName) &&
                    StringUtils.isNotBlank(activityId) &&
                    StringUtils.isNotBlank(taskName)) {
                // 流程自定义标题
                String customTitle = flowTitleExpressionResultRepository.getTitleExpressionResultByProcessInstanceIdAndActivityId(processInstanceId, activityId);
                tmpVo.setTitleName(StringUtils.isBlank(customTitle) ? processDefinitionName : customTitle);
                tmpVo.setNodeTitleName(taskName);
            }
            return tmpVo;
        }).collect(Collectors.toList());
        return handleRelVos;
    }

    public List<FlowFormProcessInstanceHandleRel> getHandleRels(FormProcessInstanceHandleRelExample queryCondition) {
        if (Objects.isNull(queryCondition)) {
            return null;
        }
        return formProcessInstanceHandleRelDAO.selectByExample(queryCondition);
    }

    private List<FormProcessInstanceHandleRelVo> convertToVoNoPage(List<FlowFormProcessInstanceHandleRel> sources) {
        if(CollectionUtils.isEmpty(sources)) {
            return Collections.emptyList();
        }
        List<FormProcessInstanceHandleRelVo> handleRelVos = sources.stream().map(item -> {
            FormProcessInstanceHandleRelVo tmpVo = new FormProcessInstanceHandleRelVo();
            BeanUtils.copyProperties(item, tmpVo);
            return tmpVo;
        }).collect(Collectors.toList());
        return handleRelVos;
    }

    @Override
    public void deleteInfo(String processInstanceId, String nodeCode) {
        formProcessInstanceHandleRelDAO.deleteInfo(processInstanceId, nodeCode);
    }
}
